﻿using System;
using System.Collections.Generic;
using System.Text;

namespace dotHTML.HTML {
    /// <summary>
    /// Represents an IFrame embedded in a page.
    /// </summary>
    [Serializable]
    public class IFrame : Element {
        /// <summary>
        /// Determines the location of an IFrame relative to its surrounding
        /// content.
        /// </summary>
        public enum Alignment {
            /// <summary>
            /// The IFrame is aligned to the left of the surrounding content.
            /// </summary>
            Left,
            /// <summary>
            /// The IFrame is aligned to the right of the surrounding content.
            /// </summary>
            Right,
            /// <summary>
            /// The IFrame is aligned in the middle of the surrounding content.
            /// </summary>
            Middle,
            /// <summary>
            /// The IFrame is aligned at the top of the surrounding content.
            /// </summary>
            Top,
            /// <summary>
            /// The IFrame is aligned at the bottom of the surrounding content.
            /// </summary>
            Bottom
        }

        /// <summary>
        /// Determines when to display scrollbars.
        /// </summary>
        public enum ScrollingChoices {
            /// <summary>
            /// Scrollbars are shown only when needed.
            /// </summary>
            Auto,
            /// <summary>
            /// Scrollbars are always shown.
            /// </summary>
            Yes,
            /// <summary>
            /// Scrollbars are never shown.
            /// </summary>
            No
        }

        /// <summary>
        /// Determines the sandboxing privileges for this IFrame.
        /// </summary>
        [Flags]
        public enum SandboxChoices {
            /// <summary>
            /// Allows the content to be treated as if it is from the same
            /// origin as the parent document.
            /// </summary>
            AllowSameOrigin = 1,
            /// <summary>
            /// Allows navigation from the top-level browsing context.
            /// </summary>
            AllowTopNavigation = 2,
            /// <summary>
            /// Allows form submissions.
            /// </summary>
            AllowForm = 4,
            /// <summary>
            /// Allows scripts to be run.
            /// </summary>
            AllowScripts = 8,
        }

        private Alignment? _align;
        private bool? _frameborder;
        private string _height;
        private string _longdesc;
        private int? _marginheight;
        private int? _marginwidth;
        private string _name;
        private ScrollingChoices? _scrolling;
        private SandboxChoices? _sandbox;
        private bool _seamless;
        private string _src;
        private string _srcdoc;
        private string _width;

        /// <summary>
        /// Constructs a new IFrame element.
        /// </summary>
        public IFrame() { }

        /// <summary>
        /// Constructs a new IFrame element with the given source URL.
        /// </summary>
        /// <param name="src">The source URL of this IFrame.</param>
        public IFrame(string src) {
            _src = src;
        }

        /// <summary>
        /// Determines the alignment of this IFrame.
        /// </summary>
        [Obsolete("Deprecated in HTML4 - use CSS instead.")]
        public Alignment? Align {
            get { return _align; }
            set { _align = value; }
        }

        /// <summary>
        /// Determines whether or not to draw a border between this IFrame and
        /// other IFrames.
        /// </summary>
        public bool? FrameBorder {
            get { return _frameborder; }
            set { _frameborder = value; }
        }

        /// <summary>
        /// Determines the height of this IFrame.
        /// </summary>
        /// <remarks>Implemented as a string so as to allow a percentage to be
        /// used.</remarks>
        public string Height {
            get { return _height; }
            set { _height = value; }
        }

        /// <summary>
        /// Gets or sets the URL of a long description of this IFrame's
        /// content.
        /// </summary>
        public string LongDesc {
            get { return _longdesc; }
            set { _longdesc = value; }
        }

        /// <summary>
        /// Determines the margin height of this IFrame.
        /// </summary>
        [Obsolete("Removed from HTML5 - use CSS instead.")]
        public int? MarginHeight {
            get { return _marginheight; }
            set { _marginheight = value; }
        }

        /// <summary>
        /// Determines the margin width of this IFrame.
        /// </summary>
        [Obsolete("Removed from HTML5 - use CSS instead.")]
        public int? MarginWidth {
            get { return _marginwidth; }
            set { _marginwidth = value; }
        }

        /// <summary>
        /// Determines the name of this IFrame, to be used in page navigation.
        /// </summary>
        public string Name {
            get { return _name; }
            set { _name = value; }
        }

        /// <summary>
        /// Determines the sandboxing privileges of this IFrame.
        /// </summary>
        public SandboxChoices? Sandbox {
            get { return _sandbox; }
            set { _sandbox = value; }
        }

        /// <summary>
        /// Determines when to show scrollbars on the IFrame.
        /// </summary>
        public ScrollingChoices? Scrolling {
            get { return _scrolling; }
            set { _scrolling = value; }
        }

        /// <summary>
        /// Determines if the IFrame should be rendered seamlessly.
        /// </summary>
        public bool Seamless {
            get { return _seamless; }
            set { _seamless = value; }
        }

        /// <summary>
        /// Determines the source document for this IFrame.
        /// </summary>
        public string Src {
            get { return _src; }
            set { _src = value; }
        }

        /// <summary>
        /// Determines the document source code for this IFrame.
        /// </summary>
        public string SrcDoc {
            get { return _srcdoc; }
            set { _srcdoc = value; }
        }

        /// <summary>
        /// Determines the width of this IFrame.
        /// </summary>
        /// <remarks>Implemented as a string so as to allow a percentage to be
        /// used.</remarks>
        public string Width {
            get { return _width; }
            set { _width = value; }
        }

        /// <summary>
        /// Gets a formatted string of all local attributes of this element
        /// (not including the base attributes).
        /// </summary>
        /// <param name="sb">The StringBuilder to write this element's
        /// attribute data to.</param>
        protected override void WriteLocalAttributes(StringBuilder sb) {
            AttributeWriter.Write(sb, _align, "align", true);
            if (_frameborder != null) {
                AttributeWriter.Write(sb, (_frameborder.Value ? '1' : '0'),
                    "frameborder");
            }
            AttributeWriter.Write(sb, _height, "height");
            AttributeWriter.Write(sb, _longdesc, "longdesc");
            AttributeWriter.Write(sb, _marginheight, "marginheight");
            AttributeWriter.Write(sb, _marginwidth, "marginwidth");
            AttributeWriter.Write(sb, _name, "name");
            if (_sandbox != null) { // .net 2 doesn't have Enum.HasFlag()
                ICollection<string> privileges = new LinkedList<string>();
                if ((_sandbox.Value & SandboxChoices.AllowForm) 
                    == SandboxChoices.AllowForm) {
                    privileges.Add("allow-form");
                }
                if ((_sandbox.Value & SandboxChoices.AllowSameOrigin)
                    == SandboxChoices.AllowSameOrigin) {
                    privileges.Add("allow-same-origin");
                }
                if ((_sandbox.Value & SandboxChoices.AllowScripts)
                    == SandboxChoices.AllowScripts) {
                    privileges.Add("allow-scripts");
                }
                if ((_sandbox.Value & SandboxChoices.AllowTopNavigation)
                    == SandboxChoices.AllowTopNavigation) {
                    privileges.Add("allow-top-navigation");
                }
                AttributeWriter.Write(sb, privileges, "sandbox", ' ');
            }
            AttributeWriter.Write(sb, _scrolling, "scrolling", true);
            AttributeWriter.Write(sb, _seamless, "seamless");
            AttributeWriter.Write(sb, _src, "src");
            AttributeWriter.Write(sb, _srcdoc, "srcdoc");
            AttributeWriter.Write(sb, _width, "width");
        }
    }
}
